package com.guli.mall.wms.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.guli.common.constant.WareConstant;
import com.guli.mall.serviceBase.globalException.MallException;
import com.guli.mall.wms.entity.PurchaseDetailEntity;
import com.guli.mall.wms.entity.vo.PurchaseDetailResult;
import com.guli.mall.wms.entity.vo.PurchaseWithPurchaseDetailListVo;
import com.guli.mall.wms.service.PurchaseDetailService;
import com.guli.mall.wms.service.WareSkuService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guli.common.utils.PageUtils;

import com.guli.mall.wms.mapper.PurchaseMapper;
import com.guli.mall.wms.entity.PurchaseEntity;
import com.guli.mall.wms.service.PurchaseService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;


@Service("purchaseService")
public class PurchaseServiceImpl extends ServiceImpl<PurchaseMapper, PurchaseEntity> implements PurchaseService {

    @Resource
    PurchaseDetailService purchaseDetailService;

    @Resource
    WareSkuService wareSkuService;

    @Override
    public PageUtils<PurchaseEntity> queryPage(Integer currentPage, Integer size) {

        Page<PurchaseEntity> page = new Page<>(currentPage, size);

        Page<PurchaseEntity> resultPage = this.page(page);

        return new PageUtils<PurchaseEntity>(resultPage);
    }

    @Override
    public Page<PurchaseEntity> searchPurchaseMenu(PurchaseEntity purchaseEntity, Integer currentPage, Integer size) {

        QueryWrapper<PurchaseEntity> purchaseEntityQueryWrapper = new QueryWrapper<>();

        /**
         * 这里的id封装了即可能是采购单id也可能是采购人id
         * */
        if (!ObjectUtils.isEmpty(purchaseEntity.getId())) {

            purchaseEntityQueryWrapper.and(p -> {
                p.eq("id", purchaseEntity.getId())
                        .or().eq("assignee_id", purchaseEntity.getId());
            });
        }


        if (!ObjectUtils.isEmpty(purchaseEntity.getAssigneeName())) {
            purchaseEntityQueryWrapper.like("assignee_name", purchaseEntity.getAssigneeName());
        }

        /**
         * 采购单的状态要小于等于某一个状态
         * 采购单状态[0新建，1已分配，2正在采购，3已完成，4采购失败]
         * */
        if (!ObjectUtils.isEmpty(purchaseEntity.getStatus())) {
            purchaseEntityQueryWrapper.le("status", purchaseEntity.getStatus());
        }

        Page<PurchaseEntity> page = new Page<>(currentPage, size);

        return this.page(page, purchaseEntityQueryWrapper);
    }

    @Transactional
    @Override
    public PurchaseEntity createPurchasingMenuAndMergeToIt(List<PurchaseDetailEntity> purchaseDetailEntityList, PurchaseEntity purchaseEntity) {

        PurchaseDetailEntity purchaseDetailEntity = purchaseDetailEntityList.get(0);

        if (ObjectUtils.isEmpty(purchaseDetailEntity)) {
            throw new MallException(purchaseDetailEntity.getId() + "没有分配仓库id");
        }

        for (PurchaseDetailEntity detailEntity : purchaseDetailEntityList) {
            if (!purchaseDetailEntity.getWareId().equals(detailEntity.getWareId())) {
                throw new MallException("提交的采购需求不在同一个仓库中");
            }
            if (ObjectUtils.isEmpty(detailEntity.getId())) {
                throw new MallException("其中一项的采购需求没有采购需求id");
            }

            PurchaseDetailEntity purchaseDetail = purchaseDetailService.getById(purchaseDetailEntity.getId());

            if (purchaseDetail.getStatus() > WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getValue()) {
                throw new MallException("采购需求：" + purchaseDetail.getId() + " 正在采购中，不能分配到新的采购单中");
            }

        }

        // 如果没有采购单，就创建一个采购单
        if (ObjectUtils.isEmpty(purchaseEntity)) {
            purchaseEntity = new PurchaseEntity();

            purchaseEntity.setWareId(purchaseDetailEntity.getWareId());
            // 设置采购单的状态为新建
            purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATED.getValue());

            // 创建采购单
            this.save(purchaseEntity);
        }


        for (PurchaseDetailEntity detailEntity : purchaseDetailEntityList) {

            // 更新采购需求的采购单id
            detailEntity.setPurchaseId(purchaseEntity.getId());
            // 更新采购需求的状态
            detailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.ASSIGNED.getValue());

        }

        purchaseDetailService.updateBatchById(purchaseDetailEntityList);

        return purchaseEntity;
    }

    @Override
    public Page<PurchaseEntity> buyerGetPurchaseMenuList(Long currentPage, Integer size, Long buyerId) {

        QueryWrapper<PurchaseEntity> purchaseEntityQueryWrapper = new QueryWrapper<>();

        purchaseEntityQueryWrapper.eq("assignee_id", buyerId);

        Page<PurchaseEntity> page = new Page<>(currentPage, size);

        Page<PurchaseEntity> resultPage = this.page(page, purchaseEntityQueryWrapper);

        return resultPage;
    }

    // 领取采购单
    @Transactional
    @Override
    public void getPurchaseMenu(List<Long> purchaseIdList) {

        // 确认采购单的状态是【新建，或者已领取】状态才能被领取

        List<PurchaseEntity> purchaseEntities = this.getBaseMapper().selectBatchIds(purchaseIdList);

        for (PurchaseEntity purchaseEntity : purchaseEntities) {
            if (purchaseEntity.getStatus() != WareConstant.PurchaseStatusEnum.CREATED.getValue() &&
                    purchaseEntity.getStatus() != WareConstant.PurchaseStatusEnum.RECEIVED.getValue()) {
                throw new MallException("采购单" + purchaseEntity.getId() + "正在采购中，不能领取");
            }
        }

        List<PurchaseEntity> purchaseEntityList = purchaseIdList.stream().map(purchaseId -> {
            PurchaseEntity purchaseEntity = new PurchaseEntity();

            purchaseEntity.setId(purchaseId);

            purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.RECEIVED.getValue());

            return purchaseEntity;
        }).collect(Collectors.toList());

        // 更新采购单的状态
        this.updateBatchById(purchaseEntityList);

        for (Long purchaseId : purchaseIdList) {
            QueryWrapper<PurchaseDetailEntity> wrapper = new QueryWrapper<>();

            wrapper.eq("purchase_id", purchaseId);

            PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();

            purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailStatusEnum.PURCHASING.getValue());

            purchaseDetailService.update(purchaseDetailEntity, wrapper);
        }
    }

    @Transactional
    @Override
    public void submitPurchasingResult(PurchaseWithPurchaseDetailListVo purchaseWithPurchaseDetailListVo) {

        PurchaseEntity purchaseEntity = this.getById(purchaseWithPurchaseDetailListVo.getId());

        if (ObjectUtils.isEmpty(purchaseEntity)) {
            throw new MallException("采购单id不存在");
        }

        if (purchaseEntity.getStatus() > WareConstant.PurchaseStatusEnum.PURCHASING.getValue()) {
            throw new MallException("采购单的处理结果已经被其他人提交");
        }

        PurchaseEntity purchase = new PurchaseEntity();

        purchase.setId(purchaseWithPurchaseDetailListVo.getId());

        // 采购单默认状态是完成
        purchase.setStatus(WareConstant.PurchaseStatusEnum.FINISHED.getValue());


        // 获取该采购单下的所有采购需求
        List<PurchaseDetailEntity> purchaseDetailList = purchaseDetailService.getPurchaseDetailByPurchaseId(purchaseWithPurchaseDetailListVo.getId());

        List<PurchaseDetailEntity> purchaseDetailListForUpdating = purchaseDetailList.stream().map(detail -> {

            for (PurchaseDetailResult item : purchaseWithPurchaseDetailListVo.getItems()) {

                if (detail.getId().equals(item.getItemId())) {

                    // 更新采购需求的状态
                    detail.setStatus(item.getStatus());

                    if (item.getStatus() == WareConstant.PurchaseDetailStatusEnum.FAILED.getValue()) {
                        log.warn("订单" + item.getItemId() + "采购失败");
                        /**
                         * 只要采购需求有一个采购失败，采购单的状态就是异常
                         * */
                        purchase.setStatus(WareConstant.PurchaseStatusEnum.FAILED.getValue());

                        //TODO purchase-detail 表中应该添加采购失败的原因列，实际的采购数量列，等以扩充功能

                        // 将该采购需求的状态改为异常
                        detail.setStatus(item.getStatus());

                        purchaseDetailService.updateById(detail);

                        return null; // 过滤采购失败的记录
                    }

                    return detail;
                }
            }
            return null;
        }).filter(detail -> {
            return !ObjectUtils.isEmpty(detail);
        }).collect(Collectors.toList());

        // 更新采购需求的状态
        purchaseDetailService.updateBatchById(purchaseDetailListForUpdating);

        // 更新采购之后的库存
        wareSkuService.updateWareSkuStockByPurchaseDetail(purchaseDetailListForUpdating);

        // 更新采购单的状态
        this.updateById(purchase);
    }

}